﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "PickCurveDrawElementBehavior.h"
#include "IUiView.h"
#include "IUiDocument.h"
#include "IModelView.h"
#include "IPlane.h"
#include "ICurve3d.h"
#include "ICurve2d.h"
#include "AlgorithmProject.h"
#include "IActionInputEventArgs.h"
#include "ILineEditDefinition.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace gcmp;

#define ACTION_INPUT_EDIT_OFFSET          L"EditOffsetId"

PickCurveDrawElementBehavior::PickCurveDrawElementBehavior(IDocument* pDoc)
    : m_pDoc(pDoc)
    , m_onInitActionCallback(nullptr)
    , m_onDestroyActionCallback(nullptr)
    , m_onPropertyPanelEventCallback(nullptr)
    , m_onCurvePickedCallback(nullptr)
    , m_OnCurvePreviewCallback(nullptr)
    , m_offset(0.0)
{

}

bool PickCurveDrawElementBehavior::SetOnInitActionCallback(OnInitActionCallback callback)
{
    m_onInitActionCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::SetOnDestroyActionCallback(OnDestroyActionCallback callback)
{
    m_onDestroyActionCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::SetOnPropertyPanelEventCallback(OnPropertyPanelEventCallback callback)
{
    m_onPropertyPanelEventCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::SetOnCurvePickedCallback(OnCurvePickedCallback callback)
{
    m_onCurvePickedCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::SetOnCurvePreviewCallback(OnCurvePreviewCallback callback)
{
    m_OnCurvePreviewCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::SetDefineInputDialogCallback(DefineInputDialogCallback callback)
{
    m_defineInputDialogCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::SetOnActionInputEventCallback(OnActionInputEventCallback callback)
{
    m_onActionInputEventCallback = callback;
    return true;
}

bool PickCurveDrawElementBehavior::DefinePromptMsg(std::wstring& promptMsg)
{
    promptMsg = GBMP_TR(L"请选择线");
    return true;
}

bool PickCurveDrawElementBehavior::DefineCursorType(CursorType& cursorType)
{
    cursorType = CursorType::DrawByPick;
    return true;
}

bool PickCurveDrawElementBehavior::DefineInputDialog(std::wstring& title, std::vector<OwnerPtr<IControlDefinition>>& inputItems)
{
    // 对话框标题
    title = GBMP_TR(L"拾取绘制");
    if (m_defineInputDialogCallback)
    {
        DefineInputDialogParams params;
        m_defineInputDialogCallback(params);
        title = params.title;
        inputItems = TransferOwnership(params.inputItems);
    }
    // 偏移量
    OwnerPtr<ILineEditDefinition> opInputOffsetDef = ILineEditDefinition::Create(ACTION_INPUT_EDIT_OFFSET, GBMP_TR(L"偏移量"), LineEditInputType::InputDouble);
    opInputOffsetDef->SetText(std::to_wstring(m_offset));
    inputItems.push_back(TransferOwnership(opInputOffsetDef));
    return true;
}

bool PickCurveDrawElementBehavior::OnActionInputEvent(IActionInputEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    const std::pair<std::wstring, gcmp::Any>& msg = pArgs->GetInputMessage();
    const std::wstring eventID = msg.first;
    gcmp::Any inputValue = msg.second;
    if (eventID == ACTION_INPUT_EDIT_OFFSET)
    {
        m_offset = inputValue.cast<double>();
    }
    else if (m_onActionInputEventCallback)
    {
        m_onActionInputEventCallback(pArgs);
    }
    return true;
}

bool PickCurveDrawElementBehavior::GetOffsetPlane(IUiView* pCurrentView, OwnerPtr<IPlane>& opPlane)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    opPlane = pModelView->GetWorkPlane();
    return true;
}

bool PickCurveDrawElementBehavior::GetOffsetValue(double& offset)
{
    offset = m_offset;
    return true;
}

bool PickCurveDrawElementBehavior::OnInitAction(IUiView* pCurrentView)
{
    if (m_onInitActionCallback)
    {
        m_onInitActionCallback(pCurrentView);
    }
    return true;
}

bool PickCurveDrawElementBehavior::OnDestroyAction()
{
    if (m_onDestroyActionCallback)
    {
        m_onDestroyActionCallback();
    }
    return true;
}

bool PickCurveDrawElementBehavior::OnPropertyPanelEvent(IPropertyPanelEventArgs* pArgs)
{
    if (m_onPropertyPanelEventCallback)
    {
        m_onPropertyPanelEventCallback(pArgs);
    }
    return true;
}

bool PickCurveDrawElementBehavior::OnDrawCurvePickFinished(IUiView* pCurrentView, OwnerPtr<ICurve3d> opCurve3d)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IPlane> workPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(workPlane, L"workPlane为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<ICurve2d> opCurve2d = AlgorithmProject::Project(opCurve3d.get(), workPlane.get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(opCurve2d, L"opCurve2d为空",L"GDMPLab",L"2024-03-30");

    if (m_onCurvePickedCallback)
    {
        m_onCurvePickedCallback(pCurrentView, TransferOwnership(opCurve2d));
    }
    return true;
}

bool PickCurveDrawElementBehavior::OnUpdatePreview(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& pos, OwnerPtr<ICurve3d> opCurve3d, OwnerPtr<IGraphicsNodeGroup>& opGNodeGroup)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IPlane> workPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(workPlane, L"workPlane为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<ICurve2d> opCurve2d = AlgorithmProject::Project(opCurve3d.get(), workPlane.get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(opCurve2d, L"opCurve2d为空",L"GDMPLab",L"2024-03-30");

    if (m_OnCurvePreviewCallback)
    {
        m_OnCurvePreviewCallback(pCurrentView, TransferOwnership(opCurve2d), opGNodeGroup);
    }
    return true;
}
